Understanding .NET Application Domains

Under the .NET platform, executables are not hosted directly within a Windows process, as is the case in traditional unmanaged applications. Rather, a .NET executable is hosted by a logical partition within a process termed an application domain. As you will see, a single process may contain multiple application domains, each of which is hosting a .NET executable. This additional subdivision of a traditional Windows process offers several benefits, some of which are as follows:

As mentioned, a single process can host any number of AppDomains, each of which is fully and completely isolated from other AppDomains within this process (or any other process). Given this fact, be very aware that an application running in one AppDomain is unable to obtain data of any kind (global variables or static fields) within another AppDomain unless they make use of a distributed programming protocol (such as Windows Communication Foundation).

While a single process may host multiple AppDomains, this is not typically the case. At the very least, an OS process will host what is termed the default application domain. This specific application domain is automatically created by the CLR at the time the process launches. After this point, the CLR creates additional application domains on an as-needed basis.

The System.AppDomain Class

The .NET platform allows you to programmatically monitor app domains, create new app domains (or unload them) at runtime, load assemblies into app domains, and a whole slew of additional tasks, using the AppDomain class in the System namespace of mscorlib.dll. Table 16-5 documents some useful methods of the AppDomain class (consult the .NET Framework 4.0 SDK documentation for full details).

Table 16-5. Select Methods of AppDomain

Method Meaning in Life
CreateDomain() This static method allows you to create a new AppDomain in the current process.
CreateInstance() Creates an instance of a type in an external assembly, after loading said assembly into the calling application domain.
ExecuteAssembly() This method executes an *.exe assembly within an application domain, given its file name.
GetAssemblies() This method gets the set of .NET assemblies that have been loaded into this application domain (COM-based or C-based binaries are ignored).
GetCurrentThreadId() This static method returns the ID of the active thread in the current application domain.
Load() This method is used to dynamically load an assembly into the current application domain.
Unload() This is another static method that allows you to unload a specified AppDomain within a given process.

Note The .NET platform does not allow you to unload a specific assembly from memory. The only way to programmatically unload libraries is to tear down the hosting application domain via the Unload() method.

In addition, the AppDomain class also defines a set of properties which can be useful when you wish to monitor activity of a given application domain. Table 16-6 documents some core properties of interest.

Table 16-6. Select Properties of AppDomain

Property Meaning in Life
BaseDirectory Gets the directory path that the assembly resolver uses to probe for assemblies.
CurrentDomain This static property gets the application domain for the currently executing thread
FriendlyName Gets the friendly name of the current application domain.
MonitoringIsEnabled Gets or sets a value that indicates whether CPU and memory monitoring of application domains is enabled for the current process. Once monitoring is enabled for a process, it cannot be disabled.
SetupInformation Gets the configuration details for a given application domain, represented by an AppDomainSetup object.

Last but not least, the AppDomain class supports a set of events that correspond to various aspects of an application domain’s life cycle. Table 16-7 shows some of the more useful events you can hook into.

Table 16-7. Select Events of the AppDomain Type

Event Meaning in Life
AssemblyLoad Occurs when an assembly is loaded into memory.
AssemblyResolve This event will fire when the assembly resolver cannot find the location of a required assembly.
DomainUnload Occurs when an AppDomain is about to be unloaded from the hosting process.
FirstChanceException This event allows you to be notified that an exception has been thrown from the application domain, before the CLR will begin looking for a fitting catch statement.
ProcessExit Occurs on the default application domain when the default application domain’s parent process exits.
UnhandledException Occurs when an exception is not caught by an exception handler.